#include "ASMInstruction.hpp"
#include "CodeGen.hpp"
#include "Module.hpp"

#include <iostream>
#include <memory>
#include <unordered_map>

void translate_main(CodeGen *codegen); // 将 main 函数翻译为汇编代码

int main() {
    auto *module = new Module();
    auto *codegen = new CodeGen(module);

    // 告诉汇编器将汇编放到代码段
    codegen->append_inst(".text", ASMInstruction::Atrribute);

    translate_main(codegen);

    std::cout << codegen->print();
    delete codegen;
    delete module;
    return 0;
}

// TODO: 按照自己的理解翻译main函数，可以按照注释中的步骤，也可自由发挥
void translate_main(CodeGen *codegen) {
    std::unordered_map<std::string, int> offset_map;

    /* 声明 main 函数 */
    codegen->append_inst(".globl main", ASMInstruction::Atrribute);
    codegen->append_inst(".type main, @function", ASMInstruction::Atrribute);

    /* main 函数开始 */
    codegen->append_inst("main", ASMInstruction::Label);

    /* Prologue */
    codegen->append_inst("addi sp, sp, -32");
    codegen->append_inst("sd ra, 24(sp)");
    codegen->append_inst("sd s0, 16(sp)");
    codegen->append_inst("addi s0, sp, 32");

    /* label_entry */
    codegen->append_inst(".main_label_entry", ASMInstruction::Label);

    /* %op0 = alloca float */
    codegen->append_inst("%op0 = alloca float", ASMInstruction::Comment);
    offset_map["%op0"] = -20;

    /* store float 0x4048F5C3, float* %op0 */
    codegen->append_inst("li a0, 0x4048F5C3");      // 3.14 的 bit pattern 放 a0
    codegen->append_inst("sw a0, -20(s0)");         // 存到 %op0

    /* %op1 = load float, float* %op0 */
    codegen->append_inst("flw ft0, -20(s0)");       // 读到 ft0

    /* %op2 = fptosi float %op1 to i32 */
    codegen->append_inst("fcvt.w.s a0, ft0");       // 转 int，放 a0 作为返回值

    /* ret i32 %op2 */
    codegen->append_inst("j main_exit");

    /* Epilogue */
    codegen->append_inst("main_exit", ASMInstruction::Label);
    codegen->append_inst("ld ra, 24(sp)");
    codegen->append_inst("ld s0, 16(sp)");
    codegen->append_inst("addi sp, sp, 32");
    codegen->append_inst("jr ra");
}
